package usj.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

public class CConexion
{
	static Logger log = Logger.getLogger(CConexion.class);
	private  Socket m_oSocket;
	private  OutputStreamWriter m_Salida;
    private  BufferedReader 	m_Entrada;
    private  String 			m_sMensaje;
    private  List<String> 		m_lParametrosMensaje;
    private  String 			m_sTipoMensaje;
    private  boolean			m_bSalir=false;
    private  CBaseDatos			m_baseDatos;
    private	 String 			m_sNameUser;
    private	 int	 			m_iIdUser;
    private  boolean			m_bLogin=false;
	
	
	public CConexion(Socket sock) throws Exception
	{
		m_baseDatos = new CBaseDatos();
		m_sNameUser = "";
		m_iIdUser 	= -1;
		
		m_oSocket= sock;
		m_Salida 	= new OutputStreamWriter(m_oSocket.getOutputStream());
		m_Entrada 	= new BufferedReader( new InputStreamReader(m_oSocket.getInputStream()));		
		m_Salida.flush();
		sendMessage( DameMsgHello() );		
		setSalir(false);
		m_lParametrosMensaje = new ArrayList<String>();
	}
	
	public boolean Procesar() throws Exception
	{	
		m_sMensaje="";
		m_sTipoMensaje="";
		do			
		{
			try
			{				
				m_sMensaje = m_Entrada.readLine();
				if(m_sMensaje != null )
				{
					m_sMensaje+= "\r\n";
				
	                log.info("client> INICIO\r\n\r\n" + m_sMensaje + "\r\n\r\nFIN");    
	                if( m_sMensaje.endsWith("\r\n") ||  m_sMensaje.endsWith("##&&") )               
	                {
	                	ProcesaMensaje ( m_sMensaje );
	                	if(!m_sTipoMensaje.equals("QUIT") && m_oSocket.isConnected())
	                	{
		                	String respuesta = DameRespuestaMensaje(m_sTipoMensaje, m_lParametrosMensaje );
		                	sendMessage( respuesta );
		                	if(m_sTipoMensaje.equals("LIST") || m_sTipoMensaje.equals("DELE")  || m_sTipoMensaje.equals("RETR") )
		                	{
		                		m_oSocket.close();
		                	}
		                	m_sMensaje = "";
		                	m_sTipoMensaje="";
		                	
	                	}
	                }
				}
            }
            catch(Exception e)
            {
            	setSalir(true);
            	log.error("Data received in unknown format" + e.getMessage() );
            	throw( new IOException("Error en la recepción " , e ) );
            }
			
		}while(!m_sTipoMensaje.equals("QUIT") && m_oSocket.isConnected());
		m_oSocket.close();
		Clog.BorrarLogUsuario(m_sNameUser);
		
		return false;
		
	}
	
	void sendMessage(String msg) throws Exception
	{
        try
        {
            m_Salida.write(msg);
            m_Salida.flush();
            log.info("server>" + msg);
        }
        catch(Exception e)
        {
        	setSalir(true);
        	log.error(e.getMessage());
        	throw( new Exception("Error al mandar mensaje" +  msg , e ) );
        }        
	}
	private String eliminarCaracteres(String msg)
	{
		String rtn= msg ;
		
		rtn = rtn.replace(".","");
		rtn = rtn.replace("\r","");
		rtn = rtn.replace("\n","");
		rtn = rtn.replace("\n","");
		rtn = rtn.replace("#","");
		rtn = rtn.replace("&","");
		
		return rtn;
		
	}
	public void ProcesaMensaje( String msg )
	{
		m_lParametrosMensaje.clear();
		String msgTemp = eliminarCaracteres(msg);	
		
		log.debug("MSG RESULTADO |" + msgTemp + "|" );
		
		String[] arrayparam = msgTemp.split(" ") ;
		 
		 m_sTipoMensaje = arrayparam [0].toUpperCase();
		 
		 for(String  s : arrayparam)
		 {			   
			 m_lParametrosMensaje.add(s);
		 }		
	}
	
	private String  dameListaMsgUsuario()
	{ 
		String rtn= m_baseDatos.dameListaMsgDeUser(m_sNameUser);
		return rtn;
	}
	private int  dameNumMsgUsuario()
	{ 
		int rtn=m_baseDatos.dameNumMsgUsuario(m_sNameUser);		
		return rtn;
	}
	
	
	private int  dameTamMsgUsuario()
	{ 
		int rtn=m_baseDatos.dameTamMsgUsuario(m_sNameUser);
		return rtn;
	}
	
	private String dameStatUsuario()
	{
		String rtn="";
		int iTotalMsg = dameNumMsgUsuario();
		int iTotalTam = dameTamMsgUsuario();
		rtn = "+OK " + String.valueOf(iTotalMsg) + " " + String.valueOf(iTotalTam) + "\r\n";
		return rtn;
	}
	
	private String dameMsgUsuario(int idmsg)
	{
		String rtn=m_baseDatos.dameMsgDeUserConId(m_sNameUser, idmsg);		
		return rtn;
	}
	
	private String dameEliminarMsgUsuario(int idmsg)
	{
		String rtn=m_baseDatos.eliminaMsgDeUserConId(m_sNameUser, idmsg);		
		return rtn;
	}
	
	
	public String DameRespuestaMensaje(String Tipo , List<String> parametros )
	{
		String msg="";
		
		log.info("Mensaje a tratar :" + Tipo +" Parametros : " + parametros.toString());		
		
	    if(m_bLogin)
		{
			switch (Tipo) 
			{
				case "STAT":
				{
					msg = dameStatUsuario();
					break;
				}
				
				case "LIST":
				{
					msg=dameListaMsgUsuario();
					break;
				}
				
				case "RETR":
				{
					int idmsg = Integer.parseInt(parametros.get(1));
					msg= dameMsgUsuario(idmsg);
					break;
				}				
				
				case "DELE":
				{
					int idmsg = Integer.parseInt(parametros.get(1));
					msg= dameEliminarMsgUsuario(idmsg);
					break;
				}
					
			}
		}
	    else
	    {
	    	log.info("NO ESTAMOS REGISTRADOS ESPERANDO USER");
	    	log.info("|"+Tipo+"|");
	    	if(Tipo.equals("USER") || Tipo.equals("PASS") )    	
	    	{
	    		switch (Tipo) 
	    		{				    
			    	case "USER":
					{
						
						m_sNameUser = parametros.get(1); 
						m_iIdUser = m_baseDatos.dameIdUsuario(m_sNameUser);
						
						if(m_iIdUser == -1 )
						{
							msg="-ERR Unkown user.\r\n";
							m_sNameUser = "";
							m_iIdUser 	= -1;						
						}
						else
						{																		
							msg="+OK Password required\r\n";										
						}				
						break;
					}
					
					case "PASS":
					{
						String sPassWord = parametros.get(1);
						m_iIdUser = m_baseDatos.dameIdUsuarioConPassword(m_sNameUser,sPassWord);
						if(m_iIdUser == -1)
						{
							msg= "–ERR Login Failed.\r\n";
							m_bLogin=false;
						}
						else
						{
							msg= "+OK User logged in.\r\n";
							m_bLogin=true;
							Clog.CreaLogUsuario(m_sNameUser);
						}
						break;
					}
	    		}
	    	}
	    	else
	    	{
				msg="-ERR User not logged in. Send USER command.\r\n";
			}	    	
			
	    }
		
		return msg;		
	}
	
	public String DameMsgHello()
	{
		String msg;
		msg= "+OK Service Ready.\r\n";
		return msg;
	}

	public boolean getSalir() {
		return m_bSalir;
	}

	public void setSalir(boolean m_bSalir) 
	{
		this.m_bSalir = m_bSalir;
	}
	
		
}

